package edu.scau.mis.system.security.filter;

import edu.scau.mis.system.security.domain.LoginUser;
import edu.scau.mis.system.security.service.TokenService;
import edu.scau.mis.system.security.utils.SecurityUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Arrays;

/**
 * token过滤器 验证token有效性
 * 作用：它从请求中提取 Token，解析用户信息，并将用户信息存储到 SecurityContext 中，供后续过滤器使用。
 *
 * 线程安全：由于 SecurityContext 是与当前线程绑定的，因此每个请求都能正确获取到自己的用户信息
 *
 */
//自定义的 Token 过滤器会放在 UsernamePasswordAuthenticationFilter 之前，以便在表单登录之前处理 Token 认证。
@Component("misAuthenticationTokenFilter")
public class MisAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private TokenService tokenService;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        // 从请求头中获取token
        LoginUser loginUser = tokenService.getLoginUser(request);//根据request.getHeader("Authorization")获取token从Redis中查询loginUser对象
        System.out.println(loginUser);
        if(loginUser != null && SecurityUtils.getAuthentication() == null) {//信息有效且当前请求未认证
            // 如果认证过期，抛出CredentialsExpiredException
            if(loginUser.getExpireTime() < System.currentTimeMillis()) {
                throw new CredentialsExpiredException("用户认证有效期已过，请重新登录");

            }
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));//将请求的详细信息（如IP地址、Session ID等）设置到认证对象中。
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);//将认证信息保存到Spring Security的上下文中
             //Spring Security 使用 ThreadLocal 将 SecurityContext 绑定到当前请求线程。
            //这意味着每个请求线程都有自己独立的 SecurityContext，从而确保不同用户的请求不会互相干扰
            //因此获取的一定是当前用户的认证信息。
        }
        chain.doFilter(request, response);//将请求和响应传递给下一个过滤器或目标资源
    }
    //由于没有设置认证信息到SecurityContextHolder，后续的Spring Security过滤器
    // （如UsernamePasswordAuthenticationFilter）将会处理这个请求。如果请求是针对受保护的资源，
    // 并且没有其他方式来认证用户（例如表单登录、基本认证等），
    // 那么最终用户将会收到一个未认证的响应，通常是HTTP状态码401（未授权）或者被重定向到登录页面。



}

